/*
socket
*/

// package main

// import (
// 	"log"
// 	"net"
// )

// func main() {
// 	//设置超时机制
// 	// conn, err := net.DialTimeout("tcp", "www.baidu.com:80", time.Second*10)
// 	conn, err := net.Dial("tcp", "www.baidu.com:80")
// 	if err != nil {
// 		log.Fatal("链接失败！", err)
// 	}
// 	defer conn.Close()
// 	log.Println("链接成功!")
// 	conn.Write([]byte("GET / HTTP/1.1\r\nHost:www.baidu.com\r\nUser-Agent: curl/7.55.1\r\nAccept: */*\r\n"))
// 	var buf = make([]byte, 1024)
// 	conn.Read(buf)
// 	log.Println(string(buf))
// }

// package main

// import (
// 	"net"
// 	"log"
// )

// func checkErr(err error){
// 	if err !=nil{
// 		log.Fatal(err)
// 	}
// }

// func handleConn(c net.Conn){
// 	defer conn.Close()
// 	for {
// 		var buf = make([]byte, 10)
// 		log.Println("start to read from conn")
// 		n, err := c.Read(buf)
// 		checkErr(err)
// 		log.Printf("read %d bytes, content is %s\n", n, string(buf[:n]))
// 	}
// }

// func main(){
// 	l, err := net.Listen("tcp", ":8080")
// 	checkErr(err)
// 	defer l.Close()
// 	log.Println("服务启动成功！")
// 	for {
// 		c, err := l.Accept()
// 		checkErr(err)
// 		go handleConn(c)
// 	}
// }

/* 端口扫描 */
package main

import (
	"flag"
	"log"
	"net"
	"strconv"
	"strings"
	"sync"
	"time"
)

func processPortItem(port string) []string {
	var ports []string
	arr := strings.Split(port, ",")
	for _, p := range arr {
		if strings.Contains(p, "-") {
			ports = append(ports, rangeToArr(p)...)
		} else {
			ports = append(ports, p)
		}
	}
	return ports
}

func rangeToArr(s string) []string {
	if strings.Contains(s, "-") {
		var arr []string
		from, _ := strconv.Atoi(strings.Split(s, "-")[0])
		to, _ := strconv.Atoi(strings.Split(s, "-")[1])
		if from == 0 {
			from = 1
		}
		if to == 0 {
			to = 65535
		}
		for i := from; i <= to; i++ {
			arr = append(arr, strconv.Itoa(i))
		}
		return arr
	} else {
		return []string{s}
	}
}

func scan(ip string, port string, wg *sync.WaitGroup) {
	conn, err := net.DialTimeout("tcp", ip+":"+port, time.Second)
	if err != nil {
		wg.Done()
		return
	}
	wg.Done()
	defer conn.Close()
	log.Println(ip, port, "端口开放")
}

func main() {
	ip := flag.String("h", "127.0.0.1", "指定主机IP")
	port := flag.String("p", "1-1000", "指定扫描的端口")
	flag.Parse()
	log.Println("扫描的端口为:", *ip, *port)
	wg := &sync.WaitGroup{}
	for _, p := range processPortItem(*port) {
		wg.Add(1)
		go scan(*ip, p, wg)
	}
	wg.Wait()
}
